#region Copyright
/// <copyright>
/// Copyright (c) 2007 Ilia Shramko.
/// Released under the terms of the GNU General Public License.
/// </copyright>
#endregion

using System;
using System.Runtime.InteropServices;
using System.Text;

namespace Osh
{
	public static class Win32
	{
		[StructLayout(LayoutKind.Sequential)]
		public struct MSG
		{
			public IntPtr hwnd;
			public int message;
			public IntPtr wParam;
			public IntPtr lParam;
			public int time;
			public int pt_x;
			public int pt_y;
		}

		[StructLayout(LayoutKind.Sequential)]
		public struct POINT
		{
			public int x;
			public int y;

			public POINT(int x, int y)
			{
				this.x = x;
				this.y = y;
			}
		}

		[StructLayout(LayoutKind.Sequential)]
		public struct RECT
		{
			public int left;
			public int top;
			public int right;
			public int bottom;
		}

		[StructLayout(LayoutKind.Sequential)]
		public class COMRECT
		{
			public int left;
			public int top;
			public int right;
			public int bottom;

			public COMRECT()
			{
			}

			public COMRECT(System.Drawing.Rectangle r)
			{
				this.left = r.X;
				this.top = r.Y;
				this.right = r.Right;
				this.bottom = r.Bottom;
			}

			public COMRECT(int left, int top, int right, int bottom)
			{
				this.left = left;
				this.top = top;
				this.right = right;
				this.bottom = bottom;
			}

			public static COMRECT FromXYWH(int x, int y, int width, int height)
			{
				return new COMRECT(x, y, x + width, y + height);
			}

			public override string ToString()
			{
				return string.Concat(new object[] {
					"Left = ", this.left,
					" Top ", this.top,
					" Right = ", this.right,
					" Bottom = ", this.bottom });
			}
		}

		[StructLayout(LayoutKind.Sequential)]
		public struct WINDOWPOS
		{
			public IntPtr hwnd;
			public IntPtr hwndInsertAfter;
			public int x;
			public int y;
			public int cx;
			public int cy;
			public int flags;
		}

		[StructLayout(LayoutKind.Sequential)]
		public class SecurityAttributes
		{
			public int nLength;
			public IntPtr lpSecurityDescriptor;
			public bool bInheritHandle;
		}

		[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
		public struct FILETIME
		{
			public static readonly FILETIME Zero;
			public uint Low;
			public uint High;

			static FILETIME()
			{
				FILETIME.Zero = new FILETIME(0);
			}

			public FILETIME(long time)
			{
				this.Low = (uint)time;
				this.High = (uint)(time >> 0x20);
			}

			public long ToLong()
			{
				return ((long)this.High << 0x20) | (long)this.Low;
			}

			public bool IsNull
			{
				get
				{
					if(this.Low == 0)
						return (this.High == 0);
					return false;
				}
			}
		}

		[ComVisible(true)]
		[StructLayout(LayoutKind.Sequential)]
		public class DOCHOSTUIINFO
		{
			[MarshalAs(UnmanagedType.U4)]
			public int cbSize;
			[MarshalAs(UnmanagedType.I4)]
			public int dwFlags;
			[MarshalAs(UnmanagedType.I4)]
			public int dwDoubleClick;
			[MarshalAs(UnmanagedType.I4)]
			public int dwReserved1;
			[MarshalAs(UnmanagedType.I4)]
			public int dwReserved2;
			public DOCHOSTUIINFO()
			{
				this.cbSize = Marshal.SizeOf(typeof(DOCHOSTUIINFO));
			}
		}

		[StructLayout(LayoutKind.Sequential)]
		public sealed class DVTARGETDEVICE
		{
			public int tdSize;
			public short tdDriverNameOffset;
			public short tdDeviceNameOffset;
			public short tdPortNameOffset;
			public short tdExtDevmodeOffset;
			public DVTARGETDEVICE()
			{
			}
		}

		[StructLayout(LayoutKind.Sequential)]
		public sealed class LOGPALETTE
		{
			public short palVersion;
			public short palNumEntries;
			public LOGPALETTE()
			{
			}
		}

		[StructLayout(LayoutKind.Sequential)]
		public class BITMAP
		{
			public int bmType;
			public int bmWidth;
			public int bmHeight;
			public int bmWidthBytes;
			public short bmPlanes;
			public short bmBitsPixel;
			public IntPtr bmBits;
			public BITMAP()
			{
				this.bmBits = IntPtr.Zero;
			}
		}
 
		[StructLayout(LayoutKind.Sequential)]
		public struct BITMAPINFO_FLAT
		{
			public int bmiHeader_biSize;
			public int bmiHeader_biWidth;
			public int bmiHeader_biHeight;
			public short bmiHeader_biPlanes;
			public short bmiHeader_biBitCount;
			public int bmiHeader_biCompression;
			public int bmiHeader_biSizeImage;
			public int bmiHeader_biXPelsPerMeter;
			public int bmiHeader_biYPelsPerMeter;
			public int bmiHeader_biClrUsed;
			public int bmiHeader_biClrImportant;
			[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x400)]
			public byte[] bmiColors;
		}
		
		[StructLayout(LayoutKind.Sequential)]
		public class BITMAPINFOHEADER
		{
			public int biSize;
			public int biWidth;
			public int biHeight;
			public short biPlanes;
			public short biBitCount;
			public int biCompression;
			public int biSizeImage;
			public int biXPelsPerMeter;
			public int biYPelsPerMeter;
			public int biClrUsed;
			public int biClrImportant;
			public BITMAPINFOHEADER()
			{
				this.biSize = 40;
			}
		}

		public enum DVASPECT
		{
			DVASPECT_CONTENT = 1,
			DVASPECT_THUMBNAIL = 2,
			DVASPECT_ICON = 4,
			DVASPECT_DOCPRINT = 8
		}

		public enum ADVF
		{
			ADVF_NODATA = 1,
			ADVF_PRIMEFIRST = 2,
			ADVF_ONLYONCE = 4,
			ADVFCACHE_NOHANDLER = 8,
			ADVFCACHE_FORCEBUILTIN = 16,
			ADVFCACHE_ONSAVE = 32,
			ADVF_DATAONSTOP = 64
		};

		public enum BiCompression
		{
			BI_RGB        = 0,
			BI_RLE8       = 1,
			BI_RLE4       = 2,
			BI_BITFIELDS  = 3,
			BI_JPEG       = 4,
			BI_PNG        = 5
		}

		public enum DIBCOLORS
		{
			DIB_RGB_COLORS = 0,
			DIB_PAL_COLORS = 1
		}

		public enum DOCHOSTUIDBLCLK
		{
			DOCHOSTUIDBLCLK_DEFAULT = 0,
			DOCHOSTUIDBLCLK_SHOWPROPERTIES = 1,
			DOCHOSTUIDBLCLK_SHOWCODE = 2
		}

		[Flags]
		public enum DOCHOSTUIFLAG
		{
			DOCHOSTUIFLAG_DIALOG = 0x00000001,
			DOCHOSTUIFLAG_DISABLE_HELP_MENU = 0x00000002,
			DOCHOSTUIFLAG_NO3DBORDER = 0x00000004,
			DOCHOSTUIFLAG_SCROLL_NO = 0x00000008,
			DOCHOSTUIFLAG_DISABLE_SCRIPT_INACTIVE = 0x00000010,
			DOCHOSTUIFLAG_OPENNEWWIN = 0x00000020,
			DOCHOSTUIFLAG_DISABLE_OFFSCREEN = 0x00000040,
			DOCHOSTUIFLAG_FLAT_SCROLLBAR = 0x00000080,
			DOCHOSTUIFLAG_DIV_BLOCKDEFAULT = 0x00000100,
			DOCHOSTUIFLAG_ACTIVATE_CLIENTHIT_ONLY = 0x00000200,
			DOCHOSTUIFLAG_OVERRIDEBEHAVIORFACTORY = 0x00000400,
			DOCHOSTUIFLAG_CODEPAGELINKEDFONTS = 0x00000800,
			DOCHOSTUIFLAG_URL_ENCODING_DISABLE_UTF8 = 0x00001000,
			DOCHOSTUIFLAG_URL_ENCODING_ENABLE_UTF8 = 0x00002000,
			DOCHOSTUIFLAG_ENABLE_FORMS_AUTOCOMPLETE = 0x00004000,
			DOCHOSTUIFLAG_ENABLE_INPLACE_NAVIGATION = 0x00010000,
			DOCHOSTUIFLAG_IME_ENABLE_RECONVERSION = 0x00020000,
			DOCHOSTUIFLAG_THEME = 0x00040000,
			DOCHOSTUIFLAG_NOTHEME = 0x00080000,
			DOCHOSTUIFLAG_NOPICS = 0x00100000,
			DOCHOSTUIFLAG_NO3DOUTERBORDER = 0x00200000,
			DOCHOSTUIFLAG_DELEGATESIDOFDISPATCH = 0x00400000
		}

		[Flags]
		public enum OLECONTF
		{
			OLECONTF_EMBEDDINGS = 1,
			OLECONTF_LINKS = 2,
			OLECONTF_OTHERS = 4,
			OLECONTF_ONLYUSER = 8,
			OLECONTF_ONLYIFRUNNING = 16
		}


		/// <summary>
		/// Incomplete list of values associated with the actions that can be taken in a URL security zone.
		/// </summary>
		public enum UrlAction
		{
			/// <summary>
			/// Minimum value for a URL action script flag.
			/// </summary>
			URLACTION_SCRIPT_MIN = 0x00001400,

			/// <summary>
			/// Do not use ActiveX safety for objects created by scripts.
			/// </summary>
			URLACTION_SCRIPT_OVERRIDE_SAFETY = 0x00001401,
			
			/// <summary>
			/// Determines whether the resource is allowed to access data sources across domains.
			/// </summary>
			URLACTION_CROSS_DOMAIN_DATA = 0x00001406,

			/// <summary>
			/// Maximum value for a URL action script flag.
			/// </summary>
			URLACTION_SCRIPT_MAX = 0x000015ff,
		}

		public enum UrlPolicy
		{
			URLPOLICY_ALLOW = 0,
			URLPOLICY_QUERY = 1,
			URLPOLICY_DISALLOW = 3,
		}

		[Flags]
		public enum WindowStyles
		{
			WS_OVERLAPPED       = 0x00000000,
			WS_POPUP            = unchecked((int)0x80000000),
			WS_CHILD            = 0x40000000,
			WS_MINIMIZE         = 0x20000000,
			WS_VISIBLE          = 0x10000000,
			WS_DISABLED         = 0x08000000,
			WS_CLIPSIBLINGS     = 0x04000000,
			WS_CLIPCHILDREN     = 0x02000000,
			WS_MAXIMIZE         = 0x01000000,
			WS_CAPTION          = 0x00C00000,     /* WS_BORDER | WS_DLGFRAME  */
			WS_BORDER           = 0x00800000,
			WS_DLGFRAME         = 0x00400000,
			WS_VSCROLL          = 0x00200000,
			WS_HSCROLL          = 0x00100000,
			WS_SYSMENU          = 0x00080000,
			WS_THICKFRAME       = 0x00040000,
			WS_GROUP            = 0x00020000,
			WS_TABSTOP          = 0x00010000,

			WS_MINIMIZEBOX      = 0x00020000,
			WS_MAXIMIZEBOX      = 0x00010000,

			WS_TILED            = WS_OVERLAPPED,
			WS_ICONIC           = WS_MINIMIZE,
			WS_SIZEBOX          = WS_THICKFRAME,
			WS_TILEDWINDOW      = WS_OVERLAPPEDWINDOW,

			// Common Window Styles
			WS_OVERLAPPEDWINDOW = (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX),
			WS_POPUPWINDOW      = (WS_POPUP | WS_BORDER | WS_SYSMENU),
			WS_CHILDWINDOW      = (WS_CHILD),
		}

		public enum OLECMDID
		{
			OLECMDID_SHOWSCRIPTERROR = 40,
		}

		public const int MAX_PATH = 260;

		public const int INVALID_HANDLE_VALUE = -1;

		// Generic rights
		public const uint GENERIC_READ        = 0x80000000;
		public const uint GENERIC_WRITE       = 0x40000000;

		// Share mode
		public const uint FILE_SHARE_READ     = 0x00000001;
		public const uint FILE_SHARE_WRITE    = 0x00000002;
		public const uint FILE_SHARE_DELETE   = 0x00000004;

		// File creation flags
		public const uint CREATE_NEW          = 1;
		public const uint CREATE_ALWAYS       = 2;
		public const uint OPEN_EXISTING       = 3;
		public const uint OPEN_ALWAYS         = 4;
		public const uint TRUNCATE_EXISTING   = 5;

		// File flags
		public const uint FILE_FLAG_WRITE_THROUGH         = 0x80000000;
		public const uint FILE_FLAG_OVERLAPPED            = 0x40000000;
		public const uint FILE_FLAG_NO_BUFFERING          = 0x20000000;
		public const uint FILE_FLAG_RANDOM_ACCESS         = 0x10000000;
		public const uint FILE_FLAG_SEQUENTIAL_SCAN       = 0x08000000;
		public const uint FILE_FLAG_DELETE_ON_CLOSE       = 0x04000000;
		public const uint FILE_FLAG_BACKUP_SEMANTICS      = 0x02000000;
		public const uint FILE_FLAG_POSIX_SEMANTICS       = 0x01000000;
		public const uint FILE_FLAG_OPEN_REPARSE_POINT    = 0x00200000;
		public const uint FILE_FLAG_OPEN_NO_RECALL        = 0x00100000;
		public const uint FILE_FLAG_FIRST_PIPE_INSTANCE   = 0x00080000;

		// Error codes
		public const int ERROR_ALREADY_EXISTS  = 0xB7;
		public const int ERROR_BROKEN_PIPE     = 0x6d;
		public const int ERROR_INVALID_HANDLE  = 6;
		public const int ERROR_INSUFFICIENT_BUFFER = 0x7A;
		public const int ERROR_IO_PENDING      = 0x3e5;
		public const int ERROR_MORE_DATA       = 0xEA;
		public const int ERROR_PIPE_BUSY       = 0xe7;
		public const int ERROR_PIPE_LISTENING  = 0x218;
		public const int ERROR_PIPE_NOT_CONNECTED = 0xe9;

		public const int S_OK = 0;
		public const int S_FALSE = 1;
		public const int E_NOTIMPL = unchecked((int)0x80004001);
		public const int E_NOINTERFACE = unchecked((int)0x80004002);
		public const int E_POINTER = unchecked((int)0x80004003);
		public const int E_FAIL = unchecked((int)0x80004005L);
		public const int E_INVALIDARG = unchecked((int)0x80070057);
		public const int E_UNEXPECTED = unchecked((int)0x8000FFFFL);

		public const int INET_E_USE_DEFAULT_PROTOCOLHANDLER = unchecked((int)0x800C0011);
		public const int INET_E_DEFAULT_ACTION = INET_E_USE_DEFAULT_PROTOCOLHANDLER;

		// Generic OLE errors that may be returned by many inerfaces
		public const int OLE_E_FIRST = unchecked((int)0x80040000L);
		public const int OLE_E_LAST  = unchecked((int)0x800400FFL);
		public const int OLE_S_FIRST = unchecked((int)0x00040000L);
		public const int OLE_S_LAST  = unchecked((int)0x000400FFL);

		public const int OLECMDERR_E_FIRST             = unchecked((int)OLE_E_LAST+1);
		public const int OLECMDERR_E_NOTSUPPORTED      = unchecked((int)OLECMDERR_E_FIRST);
		public const int OLECMDERR_E_DISABLED          = unchecked((int)OLECMDERR_E_FIRST+1);
		public const int OLECMDERR_E_NOHELP            = unchecked((int)OLECMDERR_E_FIRST+2);
		public const int OLECMDERR_E_CANCELED          = unchecked((int)OLECMDERR_E_FIRST+3);
		public const int OLECMDERR_E_UNKNOWNGROUP      = unchecked((int)OLECMDERR_E_FIRST + 4);

		// Define the dwPipeMode values for CreateNamedPipe
		public const int PIPE_WAIT             = 0x00000000;
		public const int PIPE_NOWAIT           = 0x00000001;
		public const int PIPE_READMODE_BYTE    = 0x00000000;
		public const int PIPE_READMODE_MESSAGE = 0x00000002;
		public const int PIPE_TYPE_BYTE        = 0x00000000;
		public const int PIPE_TYPE_MESSAGE     = 0x00000004;

		// Window messages
		public const int WM_SETTEXT            = 0x000C;
		public const int WM_KEYFIRST           = 0x0100;
		public const int WM_KEYDOWN            = 0x0100;
		public const int WM_KEYUP              = 0x0101;
		public const int WM_CHAR               = 0x0102;
		public const int WM_KEYLAST            = 0x0109;
		public const int WM_MOUSEFIRST         = 0x0200;
		public const int WM_MOUSELAST          = 0x020D;
		public const int WM_WINDOWPOSCHANGING  = 0x0046;

		public const int WM_USER               = 0x0400;
		public const int WM_APP                = 0x8000;

		public const int WM_LBUTTONDOWN        = 0x0201;
		public const int WM_LBUTTONUP          = 0x0202;

		public const int TBM_GETPOS            = WM_USER;
		public const int TBM_GETRANGEMIN       = WM_USER + 1;
		public const int TBM_GETRANGEMAX       = WM_USER + 2;
		public const int TBM_SETPOS            = WM_USER + 5;
		
		public const int MK_LBUTTON            = 0x0001;

		public const int SWP_NOSIZE            = 0x0001;
		public const int SWP_NOMOVE            = 0x0002;

		public class Sockets
		{

			// Error codes

			/// <summary>
			/// Message too long. A message sent on a datagram socket was larger than
			/// the internal message buffer or some other network limit,
			/// or the buffer used to receive a datagram was smaller than the datagram itself.
			/// </summary>
			public const int WSAEMSGSIZE = 10040;

		}

		public static Guid CGID_DocHostCommandHandler = new Guid("{f38bc242-b950-11d1-8918-00c04fc2c836}");
		
		[DllImport("kernel32.dll", CharSet=CharSet.Unicode)]
		public static extern void SetLastError(uint errorCode);

		[DllImport("user32.dll", CharSet=CharSet.Auto)]
		public static extern int PostMessage(HandleRef hwnd, int msg, IntPtr wparam, IntPtr lparam);
 
		[DllImport("kernel32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
		public static extern IntPtr CreateFile(string fileName, uint desiredAccess, uint shareMode,
			SecurityAttributes securityAttributes,
			uint creationDisposition, uint flagsAndAttributes, HandleRef templateFile);

		[DllImport("kernel32.dll", SetLastError=true)]
		public static extern bool ReadFile(HandleRef hFile, IntPtr lpBuffer, int nNumberOfBytesToRead,
			out int lpNumberOfBytesRead, HandleRef lpOverLapped);

		[DllImport("kernel32.dll", SetLastError=true)]
		public static extern bool SetNamedPipeHandleState(IntPtr namedPipe,
			[In] ref uint mode, [In] IntPtr maxCollectionCount, [In] IntPtr collectDataTimeout);

		[DllImport("Kernel32", SetLastError=true)]
		public extern static bool CloseHandle(IntPtr handle);

		public static int GetHRForWin32Error(int errorCode)
		{
			return (errorCode | -2147024896); // 0x80070000
		}

		public static void ThrowExceptionForLastWin32Error()
		{
			Marshal.ThrowExceptionForHR(GetHRForWin32Error(Marshal.GetLastWin32Error()));
		}

		public static void ThrowExceptionForWin32Error(int win32Error)
		{
			Marshal.ThrowExceptionForHR(GetHRForWin32Error(win32Error));
		}

		[DllImport("user32.dll", ExactSpelling=true)]
		public static extern bool IsChild(HandleRef parent, HandleRef child);
 
		[DllImport("user32.dll", ExactSpelling=true)]
		public extern static IntPtr SetFocus(IntPtr hWnd);

		[DllImport("kernel32.dll", ExactSpelling=true)]
		public static extern int GetCurrentThreadId();

		[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
		public static extern int GetModuleFileName(HandleRef hModule, StringBuilder buffer, int length);
 
		[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
		public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

		[DllImport("user32.dll", CharSet = CharSet.Unicode)]
		public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

		[DllImport("user32.dll", CharSet = CharSet.Unicode)]
		public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, string lParam);

		[DllImport("user32.dll")]
		public static extern bool IsWindow(IntPtr hWnd);
	}
}
